<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/5/14 0014
 * Time: 下午 3:35
 */

namespace App\Common;


use App\Model\User;
use App\Utility\RedisTools;
use App\Utility\BaseEnum;
use App\GameService\games\PlayBaiRen;
use EasySwoole\EasySwoole\ServerManager;
use App\Utility\Pool\MySQLObject;
use App\Utility\DBTools;
use App\Enum\SysEnum;
use EasySwoole\EasySwoole\Config;
use EasySwoole\EasySwoole\Task\TaskManager;

/**
 * 棋牌的配置参数分类
 * 保存当前棋牌的说明数据
 * @author XCH
 *
 */
class AuthCommon
{
    public static $login_longtime = 7200;
    //用户状态
    const USER_STATUS = [0=>'禁用',1=>'正常',2=>'锁定',-1=>'删除'];
    
    /**
     * 构造函数
     * @param array $options 参数
     * @access public
     */
    public function __construct($options = [])
    {
    }
    
    
    /**
     * TODO 密码机制(单向加密不可解)
     * @param string $pwdText
     * @return string
     */
    public static  function PwdEncode($pwdText){
        $frontChar = substr(md5(substr($pwdText, 0,2)), 0,10) ; //前10位值；
        return strtoupper(md5($frontChar.$pwdText ));
    }
    
    
    /**
     * 清理掉FD的数据；
     * @param int $fdVal
     * @return boolean
     */
    public static function clearLoginFd($fdVal,&$getLoginUid=0) {
        try {
            $mapFdKey = SysEnum::getLoginFdMapKey();
            $roomFdKey = SysEnum::USER_PLAY_FDMAP_KEY;
            $disconnectKey = SysEnum::BASEDB_GAMECOMMON_DISCONFDS_KEY;
            $getId = RedisTools::Pool_hGet($mapFdKey,"login_".$fdVal);               //获取对应的用户ID和FD值
            $getRoomID = RedisTools::Pool_hGet($roomFdKey,"login_".$fdVal);          //当前用户所呆的游戏局(正在游戏中的局号－－－对接用户ID)；
            $getRoomids = !empty($getRoomID) ? json_decode($getRoomID,TRUE) : FALSE;
            if(isset($getId) && !empty($getId)){
                $getUIds = explode('-', $getId);
                $getLoginUid = isset($getUIds[0]) ? intval($getUIds[0]) : 0;
                RedisTools::Pool_hSet($disconnectKey, $fdVal , "IS_NULL");           //掉线把当前这个玩家FD的KEY置空
                BaseEnum::Logger('清理客户端：AuthCommon --> clearLoginFd--------getFd='. $fdVal .'_savekey-->'.json_encode($getUIds),'user-login');
                if(!empty($getUIds) && isset($getLoginUid) && $getLoginUid > 0){
                    
                    //TODO 游戏数据处理 清空
                    self::deleteUserGamesData($getLoginUid,$getRoomids);
                    
                    //TODO 用户数据REDIS标识下线处理
                    $userRsKey = SysEnum::USER_LOGIN_REDIS_KEY.$getLoginUid; //存储信息内容；
                    $useInfo = RedisTools::Pool_get($userRsKey);
                    $userInfo = !empty($useInfo) ? json_decode($useInfo,true): false;
                    // 用户信息修改为离线状态
                    if(!empty($userInfo)){
                        $userInfo["onlineStatus"] = 0;
                        $userInfo["onStatus"] = "DOWN";                                     //当用户：断线，离线
                        RedisTools::Pool_set($userRsKey,json_encode($userInfo),1800);       //掉线的用户保留30分钟
                    }
                    RedisTools::Pool_hDel($mapFdKey, "login_".$fdVal) ;                     //删除FD-KEY;
                }
            }
        } catch (\Throwable $throwable) {
        }
        return true;
    }
    /**
     * 强制玩家退出游戏；
     * @param int $fdVal
     * @return boolean
     */
    public static function kickLoginFd($fdVal){
        try {
            $mapFdKey = SysEnum::getLoginFdMapKey();
            $roomFdKey = SysEnum::USER_PLAY_FDMAP_KEY;
            $disconnectKey = SysEnum::BASEDB_GAMECOMMON_DISCONFDS_KEY;
            $getId = RedisTools::Pool_hGet($mapFdKey,"login_".$fdVal);               //获取对应的用户ID和FD值
            $getRoomID = RedisTools::Pool_hGet($roomFdKey,"login_".$fdVal);          //当前用户所呆的游戏局(正在游戏中的局号－－－对接用户ID)；
            $getRoomids = !empty($getRoomID) ? json_decode($getRoomID,TRUE) : FALSE;

            if (isset($getId) && !empty($getId)){
                $getUIds = explode('-', $getId);
                $getLoginUid = isset($getUIds[0]) ? intval($getUIds[0]) : 0;

                if(!empty($getUIds) && isset($getLoginUid) && $getLoginUid > 0){
                    //TODO 游戏数据处理 清空
                    self::deleteUserGamesData($getLoginUid,$getRoomids);
                    //TODO 用户数据REDIS 清空
                    RedisTools::Pool_hDel($disconnectKey, $fdVal);
                    RedisTools::Pool_hDel($roomFdKey,"login_".$fdVal);
                    RedisTools::Pool_hDel($mapFdKey, "login_".$fdVal) ;//删除FD-KEY
                    $userRsKey = SysEnum::USER_LOGIN_REDIS_KEY.$getLoginUid; //存储信息内容；
                    RedisTools::Pool_del($userRsKey);
                }
            }
        } catch (\Throwable $throwable) {
        }
    }
    
    
    /**
     * TODO 掉线处理玩家数据
     * @param int $userId
     * @param string $gameNo
     */
    public static function deleteUserGamesData($userId,$gameInfo = FALSE){
        $gameNo = FALSE;
        $roomId = FALSE;
        $gameId = FALSE;
        
        //TODO 删除当前玩家最新FD值对应关系
        RedisTools::Pool_hDel(SysEnum::SERVER_LOGIN_CLIENTS_KEY,$userId);
        
        //TODO　除掉大厅列表FD
        BaseComm::doLobbyInOrOut($userId,FALSE,FALSE);               
        
        if(isset($gameInfo)&& is_array($gameInfo)){
            $gameNo = reset($gameNo);
            $roomId = (!empty($gameInfo) && isset($gameInfo[1])) ? intval($gameInfo[1]) :0 ;
            $gameId = ($roomId>0) ? intval($roomId/10): 0 ;
        }
        
        //百人牛牛掉线清掉玩家列表        
        if($gameId && $gameId == 112 && $roomId > 0){
            PlayBaiRen::doGameOutPlay($roomId,$userId);
        }
        
        //TODO　其它操作
    }
    
    /**
     * 推送到指定FD的数据；
     * 推送所有FD的信息一样就可以这样推
     */
    public static function pushFrontWeb($fdlist,$pushContent = false){
        $fdArray = [];//推送到客户端的数据；
        if(isset($fdlist) && is_array($fdlist)){ 
            $fdArray = $fdlist;
        }else if(!is_array($fdlist) && intval($fdlist) > 0){
            $fdArray = array(intval($fdlist));
        }
        $serverIP = BaseComm::getSiteId();              //获取负载服务器IP ；
        $opcode = WEBSOCKET_OPCODE_TEXT;                //文本数据
        //$opcode = WEBSOCKET_OPCODE_BINARY;            //二进制数据格式
        if(!empty($fdArray)){                           //取所有FD用户推送；
            foreach ($fdArray as $fdval){
                $fdInfo = ServerManager::getInstance()->getSwooleServer()->connection_info($fdval);             // websocket_status 状态值
                if(isset($fdInfo) && is_array($fdInfo) && isset($fdInfo['websocket_status'])){                  //状态值
                    $pushFormat = !empty($pushContent) ? json_decode($pushContent,true) : FALSE;
                    $serverIP = !empty($serverIP) ? "siteId-".$serverIP :  @$fdInfo['remote_ip'];
                    $serverPort = $fdInfo['server_port'] ?? "0";
                    if(!empty($pushFormat) && isset($pushFormat['m']) && intval($pushFormat['m']) == BaseEnum::XYM_0X11 && !empty($pushFormat['data'])){ //加一个信息字段
                        $pushFormat['data']['routeServerIp'] = "{$serverIP}|{$serverPort}"; 
                        $pushContent = json_encode($pushFormat);                                               //转成JSON格式传数据
                    }
                    ServerManager::getInstance()->getSwooleServer() -> push($fdval,$pushContent,$opcode );      //通道其它在线等待的用户
                }else{
                    //BaseEnum::Logger("推送FD失败：Push User Failed !!!  Fd==>{$fdval}  getInfo=" .json_encode($fdInfo), 'user-login');
                }
            }
        }
    }
    
    
    /**
     * 获取代理的相应的KEY值；
     * 
     * @param int $agentId 代理ID
     */
    public static function getAgentDesKeys($agentId){
        $agentredkey = SysEnum::AGENT_DESCMAP_KEY ;
        //查询游戏数据；
        $agentKeys = RedisTools::Pool_hGet($agentredkey,$agentId);            //取数据；  
        $agentKeys = !empty($agentKeys) ? json_decode($agentKeys,true) : false ;
        if (!$agentKeys) {
            $modelUser = new User();
            $agInfo = $modelUser->getAgentById($agentId,["uid","name","desc_key","md5_key","name","ancestor_ids"]);    //取DB中的值；
            if (isset($agInfo["md5_key"]) && isset($agInfo["desc_key"]) && !empty($agInfo["md5_key"]) && !empty($agInfo["desc_key"])) {
                //把数据存入缓存中
                $agentKeys = ["name"=> $agInfo["name"],"md5Key"=> $agInfo["md5_key"],"desKey"=> $agInfo["desc_key"],"ancestor_ids"=>$agInfo["ancestor_ids"]];
                RedisTools::Pool_hSet($agentredkey,$agentId, json_encode($agentKeys));  //取数据；;
            }
        }
        return $agentKeys;
    }
    
    
    /**
     * 自动分配机器人；
     * @return boolean
     */
    public static function getRobotUser($gameId){
        $robot_rediskey = SysEnum::ROBOT_USER_KEY.$gameId;
        //登录判断玩家是否存在；
        $userModel = new User();                    //登录验证
        $userfields = ['uid','name','password','group_id','status','recUid','recUser','ancestor_ids','level','realname','gender','user_ident','head_url','points','reg_ip'];
        //机器人存储位置
        $robotResult = RedisTools::Pool_hGetAll($robot_rediskey);
        if(empty($robotResult)){
            //机器人的UID值都固定为10000_开头(所有机器人都是放在内存里面)；
            $lists = $userModel->getRobotUserByGameId($gameId, $userfields); //游戏内的机器人
            if (!empty($lists) && sizeof($lists) > 0 ) {
                //一次性全放进缓存中；
            }
        }
        
        //取机器人的过程
        foreach ($robotResult as $onestring){ //每个机器人的数据都要处理
            $robotdet = !empty($onestring) ? json_decode($onestring,true) : false ;
            if (isset($robotdet) && isset($robotdet["uid"]) && intval($robotdet["uid"]) > 0) {
                //取空闲状态的机器人信息； 
            }
        }
         
        
        /* $userName = "{$agentId}_{$account}";
        $userInfo = $userModel->getUser($userName,$userfields);
        $userSta = isset($userInfo['status']) ? intval($userInfo['status']) : -1;
        $loginUid = isset($userInfo['uid']) ? intval($userInfo['uid']) : 0;
        BaseEnum::Logger("查询玩家:playname={$userName} ,findRes=".json_encode($userInfo),"user-login");
        
        if($loginUid > 0 && $userSta===0){
            $error = BaseEnum::MSG_0XF4; //"该会员账号被禁用。如有疑问请联系客服";
            return FALSE;
        }
        //新创建一个用户信息
        $agentDetal = $userModel -> getAgentById($agentId,["uid","name","ancestor_ids"]);
        if(!$agentDetal){
            $error = BaseEnum::MSG_0XF4; //代理不存在
            return FALSE;
        }
        if(empty($userInfo) ){
            $agentRuid = (isset($agentDetal['ancestor_ids']) && !empty($agentDetal['ancestor_ids'])) ? $agentDetal['ancestor_ids'] : '10000'; //首级代理ID；
            //新用户数据；
            $userInfo = array(
                'name'=>$userName,
                'password'=>'8677D2D15C655180174AA354B897FCA9',
                'group_id'=>1,
                'status'=>1,
                'recUid'=> $agentId,
                'recUser'=> isset($agentDetal['name']) ? $agentDetal['name'] : '',
                'ancestor_ids'=> $agentRuid.",".$agentId, //上级ID值；
                'level'=>1,'realname'=> $account ,'gender' => 0,
                'user_ident'=> 1,'head_url'=>rand(1,7),
                'points'=>0,
                'reg_ip'=>BaseEnum::getClientIP()
            );
            BaseEnum::Logger("新加入玩家:playname={$userName} ,insertRes=".json_encode($userInfo),"user-login");
            //插入一条数据
            $insertRow = $userModel->dbConnector() -> insert($userModel->tableName, $userInfo) ;
            if (isset($insertRow) && intval($insertRow) > 0) {
                $loginUid = $userModel->dbConnector() -> getInsertId();
                BaseEnum::Logger("新加入玩家成功:playname={$userName} ,getUid=".$loginUid,"user-login");
            }else{
                $userInfo = FALSE ;
            }
        } */
        
        return FALSE;
    }
    
    
    /**
     * 验证登录是否成功
     * @param array $userInfo 用户信息
     */
    public static function loginCheck($userInfo,$params=false,$type='password'){
        if(!$userInfo || !$params) return false ;
        $userPwd = isset($userInfo["password"]) ? $userInfo["password"] : "";
        if(isset($type) && !empty($type) && strtoupper($type) == 'LOGIN'){      //验证信息；
            
        }else { //默认为PASS密码登录
            $parms = base64_decode($params); //密码用户Base64解密再进行验证(并且是以 pwd:开头数据)
            $inputPwd = self::PwdEncode(substr($parms,3));
            if(isset($parms) && is_string($parms) && substr($parms,0,4)== 'pwd:' && !empty($inputPwd) && !empty($userPwd) && $inputPwd == $userPwd){
                return true;
            }
        }
        return false;
    }
    
    
    /**
     * 验证当前用户是否有正在游戏中的玩法数据
     * 推送正在游戏中的数据到前端；
     */
    public static function checkGamesOnline($userid,$loginUserFd,&$returnData = FALSE){
        $steps = BaseEnum::GAME_STEP;
        //取玩家ID对应最后一次游戏数据；
        $gameChar = RedisTools::Pool_hGet(SysEnum::USER_PLAY_FDMAP_KEY, $userid);     //玩家最新游戏ID对应的号
        $lists = !empty($gameChar) ? json_decode($gameChar,TRUE): FALSE; 
        $gameNo = $lists[0] ?? FALSE ;
        if(isset($gameNo) && !empty($gameNo) && intval($userid) > 0){ 
            $gamedata = BaseComm::distMemoryRooms($gameNo);
            $gameId = isset($gamedata['gameId']) ? intval($gamedata['gameId']) : 0;
            $roomId = isset($gamedata['grid']) ? intval($gamedata['grid']) : 0;
            $gameStatus = isset($gamedata['fjStatus']) ? intval($gamedata['fjStatus']) : 0;
            $gamePlays = isset($gamedata['lists']) ? $gamedata['lists'] : FALSE;
            
            //推送到前端哪个游戏没有结束；
            $stepName = isset($steps[$gameStatus]) ? $steps[$gameStatus] : "-";
            //查询当前游戏状态：
            if (!empty($gamedata) && $gameStatus >= 0  && in_array($gameStatus, [0,1,2,3,4,5]) && !empty($gamePlays)) {                     //大于0 都是游戏中；
                
                $returnData = array("gameId"=>$gameId,"roomId"=> $roomId,"gameNo"=> $gameNo ,"step"=> $stepName,"status"=> $gameStatus);
                return TRUE;
            }
            return FALSE;
        }
    }
    
    
    /**
     * 启动服务器更新在线的服务器状态
     */
    public static function startGameServer() {
        $baseSiteId = BaseComm::getSiteId();
        $editFields = ["isStart"=>1,"lastStartTime"=> BaseEnum::getNowTime(FALSE)];
        $whereOpts = ["siteId"=>$baseSiteId];
        $res = DBTools::PoolUpdate('qc_game_site',$editFields ,$whereOpts);
        BaseEnum::Logger("启动服务器更新状态:SiteID={$baseSiteId} ,print_status=".json_encode(["update"=> $editFields,"lastRes"=>$res]) ,"user-login");
    }
    
    
    /**
     * TODO 玩家验证新的FD写入登录服务端更新缓存操作
     * @param number $userId
     * @param number $loginFd
     */
    public static function LoginOKServer($userId,$loginFd = 0){
        $baseSiteId = BaseComm::getSiteId();
        $client_key = SysEnum::SERVER_LOGIN_CLIENTS_KEY;
        $servString = RedisTools::Pool_hGet($client_key, $userId); 
        $userClients = !empty($servString) ? json_decode($servString,TRUE):FALSE; //客户端的数据
        $loginInfo = ["userId"=> $userId,'siteId'=> $baseSiteId,"loginFd"=> $loginFd , "online" => 1];
        if(!$baseSiteId || $loginFd<=0 )return FALSE;
        if (!$userClients) $userClients = [];
        $userClients[$baseSiteId] = $loginInfo;     //保存进入列表中
        RedisTools::Pool_hSet($client_key, $userId,json_encode($userClients));
        return TRUE;
    }
    
    
    /**
     * TODO 前端验证玩家登录是否成功； （前提是已经通过API完成登录才可通过）
     * @param string $userName
     * @param string $params
     * @param boolean $loginFd 玩家客户端
     */
    public static function loginWSGames($userName,$params,$loginFd = false,& $error = FALSE){
        if (empty($userName) || empty($params) ) {
            $error = 0XF2;  // 账号为空;
            return FALSE;
        }
        //取代理ID；
        $agentID = strpos($userName,'_') > 0 ?  intval(substr($userName,0,strpos($userName,'_'))) : 0; 
        if(!$agentID) $agentID = 10000; //总代理；
        
        //查询当前用户的KEY
        //第一步：代理ID，并获取当前代理的解密KEY；
        $agInfo = self::getAgentDesKeys($agentID);
        $agentKey = isset($agInfo["desKey"]) ? $agInfo["desKey"] : "" ;
        if(!$agentKey){
            $error = 0XF2;  // 代理身份异常;
            return FALSE;
        }
        //解密 $params 数据；
        $scrtStr = BaseEnum::descDecode($agentKey, $params);
        $scrData = !empty($scrtStr) ? json_decode($scrtStr,true) :false ; 
        $userYzInfo = isset($scrData["sid"]) ? $scrData["sid"] : "" ;           //身份信息
        $userLoginIp = isset($scrData["authip"]) ? $scrData["authip"] : "" ;    //玩家的登录IP字段传过来
        $userToken = isset($scrData["token"]) ? $scrData["token"] : "" ;
        
        //匹配成功；
        if (isset($agentID) && !empty($scrData) && isset($scrData["a"]) && intval($scrData["a"]) === $agentID &&  !empty($userYzInfo)) { //验证sid是否有效果；
            $userModel = new User();                                    //登录验证
            $userID = BaseEnum::descDecode("LoginUid", $userYzInfo);     //玩家ID值；  
            $userName = $userModel->getUserOneFields($userID,"name");
            
            if(!isset($userName) || empty($userName) || !$userID){
                $error = BaseEnum::MSG_0XF3 ; //"暂无该会员账号，请注册。如有疑问请联系客服";
                BaseEnum::Logger('登录失败: 暂无该会员账号，请注册', 'user-login');
                return FALSE;
            }
            
            //TODO 正式登录；要更新REDIS数据====FD更新；
            $userRsKey = SysEnum::USER_LOGIN_REDIS_KEY.$userID;                                      //存储信息内容；
            $userInfo = RedisTools::Pool_get($userRsKey);
            $userInfo = !empty($userInfo) ? json_decode($userInfo,true) : false ; 
            $firstToken = isset($userInfo['token']) ? $userInfo['token'] : "";
            $userSta = isset($userInfo['status']) ? intval($userInfo['status']) : -1;

            //TODO 验证当前TOKEN是还在有效（token字段是否变化）
            if (empty($firstToken) || (!empty($firstToken) && $userToken != strtoupper(substr($firstToken, 0,10))) ) {
                BaseEnum::Logger('登录失败: 验证信息失效，请重新登录', 'user-login');
                $error = BaseEnum::MSG_0XF7 ;       //TOKEN 用户身份失效
                return FALSE;
            }
            if($userSta===0){
                $error = BaseEnum::MSG_0XF4; //"该会员账号被禁用。如有疑问请联系客服";
                return FALSE;
            }
            //TODO 玩家信息要更新FD值；
            if ($userID > 0 && isset($userInfo["lastActiveTime"]) && BaseEnum::getNowTime(FALSE) - intval($userInfo["lastActiveTime"]) < self::$login_longtime  ) {
                $loginOldFd = $userInfo["fd"] ?? 0;
                //TODO 挤掉原来的FD
                if(intval($loginOldFd) > 0){
                    BaseEnum::Logger('检测到原来的玩家还在线，执行踢线提醒 FD = '. $loginOldFd, 'user-login');
                    TaskManager::getInstance()->async(function() use ($loginOldFd){
                        $oldUid = 0;
                        $pushdata = ['m'=>BaseEnum::XYM_0X02,"data"=>"","code"=>BaseEnum::MSG_0XF7,"level"=> 3,"msg"=> "异地登录被挤下线"];
                        //TODO 把原来的登录玩家踢线操作
                        AuthCommon::pushFrontWeb($loginOldFd ,json_encode($pushdata));
                        $rv = AuthCommon::clearLoginFd($loginOldFd,$oldUid);
                        BaseEnum::Logger('踢线成功： 原来的玩家被在其它地方登录，踢线   FD = '. $loginOldFd," getUid = {$oldUid}, res = {$rv}", 'user-login');
                    });
                }
                
                //TODO 正式登录；要更新REDIS数据；
                $userInfo["fd"] = $loginFd;
                $userInfo["onlineStatus"] = 1;
                $userInfo["onStatus"] = 'ONLINE' ;       //没有过期就行；
                $userInfo["points"] = self::getLoginUserPoints($userID);
                RedisTools::Pool_set($userRsKey, json_encode($userInfo) ,self::$login_longtime) ;                   //更新登录数据时和 
                RedisTools::Pool_hSet(SysEnum::getLoginFdMapKey(),"login_".$loginFd , $userID.'-'. $firstToken);              //对应的用户ID和FD值
                
                $playName = $userInfo['name'];
                $agLen = strlen("{$agentID}_");
                if (!empty($playName) && strlen($playName) > $agLen + 3) {
                    $playName = substr($playName, $agLen);          //取后面的部分
                }
                //TODO 验证成功返回用户信息
                return [
                    "uid"=>$userID,
                    "fd"=>$loginFd,
                    "group_id"=> $userInfo["group_id"],
                    "name"=> $playName,
                    "real_name"=>isset($userInfo['realname']) ? $userInfo['realname'] : "",
                    "points"=> $userInfo["points"],
                    "token"=>$userInfo["token"],
                    "sex"=> isset($userInfo["gender"]) ? intval($userInfo["gender"]) : 0,
                    "head_id"=> isset($userInfo["head_url"]) ? intval($userInfo["head_url"]) : 1,
                    "userLoginIp" => $userLoginIp
                ];
            }else{
                BaseEnum::Logger('登录过期；请重新登录', 'user-login');
                $error = BaseEnum::MSG_0XF1; 
            }
        }else{
            BaseEnum::Logger('数据解析失败；'. json_encode($scrData), 'user-login');
            $error = BaseEnum::MSG_0XF1;                    //数据解析失败； 请重新登录
        }
        return FALSE;
    }
    
    /**
     * 登录进入游戏
     * @param string $userName
     * @return array|array|string[][]|number[][]
     */
    public static function loginIntoGame($userName , $params = '' ,$loginFd = false,&$error= ''){
        //如果账号或者密码为空，抛出异常 “账号密码不能为空”
        if (empty($userName) || empty($params) ) {
            $error = 0XF2; // "ACCOUNT_NOT_NULL";
            return FALSE;
        }
        $userModel = new User();                    //登录验证
        $userfields = ['uid','name','password','group_id','status','recUid','recUser','ancestor_ids','level',"isNation",'realname','gender','user_ident','head_url','points','reg_ip'];
        //TODO 查询条件
        $searchOption = array(
            'name'=> ['text' => $userName,"mark"=> '='],
            'isNation'=> ['text' => 1,"mark"=> '='],
        );
        
        //数据库直接查询数据：
        $userInfo = DBTools::PoolGetOne('qc_user',$userfields,$searchOption);
        $userSta = isset($userInfo['status']) ? intval($userInfo['status']) : -1;
        $loginUid = isset($userInfo['uid']) ? intval($userInfo['uid']) : 0;
        
        if(!isset($userInfo) || empty($userInfo) || $userSta < 0 || !$loginUid){
            $error = BaseEnum::MSG_0XF3 ; //"暂无该会员账号，请注册。如有疑问请联系客服";
            return FALSE;
        }
        if($userSta===0){
            $error = BaseEnum::MSG_0XF4; //"该会员账号被禁用。如有疑问请联系客服";
            return FALSE;
        }
        
        //账户验证失败
        if(self::loginCheck($userInfo,$params,'password') !== true){
            $error = BaseEnum::MSG_0XF1; //"会员账号验证失败";
            return FALSE;
        }
        unset($userInfo["password"]);
        $userInfo["fd"] = $loginFd ;
        $userInfo["lastActiveTime"] = time();
        $userInfo["onlineStatus"]   = 1;
        $userInfo["onStatus"] = "ONLINE";           //当用户：在线状态；
        $userInfo["token"] = BaseComm::createToken($loginUid);
        $newPoints = isset($userInfo['points']) ? floatval($userInfo['points']): 0.00;
        //执行登录操作；
        
        $TB_User = $userModel->tableName;
        $logRows = BaseComm::DbQuery(function($db) use($loginUid,$TB_User){
            $res = FALSE;
            $nowtime = BaseEnum::getNowTime(false);
            if($db != NULL && $db instanceof MySQLObject){
                $res =  $db -> where("uid",$loginUid)->update($TB_User, ["login_ip" => BaseEnum::getClientIP(),"login_time"=>$nowtime,"update_time"=>$nowtime]); //登录成功
            }
            return $res;
        });
        //$logRows = $userModel -> dbConnector()->where("uid",$loginUid)->update($userModel->tableName, ["login_ip" => BaseEnum::getClientIP(),"login_time"=>$nowtime,"update_time"=>$nowtime ]); //登录成功
        if(isset($logRows) && intval($logRows) > 0){
            $userRsKey = SysEnum::USER_LOGIN_REDIS_KEY.$loginUid;                                                  //存储信息内容；
            $historyData = RedisTools::Pool_get($userRsKey);         //原登录信息；
            $historyData = !empty($historyData) ? json_decode($historyData,true) : FALSE;
            if(!empty($historyData) && isset($historyData['fd']) && intval($historyData['fd']) != $loginFd){    // 踢下线
                $pushdata = ['m'=>BaseEnum::XYM_0X02,"data"=>null,"code"=>BaseEnum::MSG_0XF7,"level"=> 3,"msg"=> "异地登录被挤下线"];
                AuthCommon::pushFrontWeb($historyData['fd'],BaseEnum::JsonEncode($pushdata));
            }
            RedisTools::Pool_set($userRsKey, json_encode($userInfo),self::$login_longtime) ;       //保存信息为JSON格式
            RedisTools::Pool_hSet(SysEnum::getLoginFdMapKey(),"login_".$loginFd , $loginUid.'-'. $userInfo["token"]);    //对应的用户ID和FD值
            //登录成功返回数据
            return [
                "uid"=>$loginUid,
                "fd"=>$loginFd,
                "group_id"=> $userInfo["group_id"],
                "name"=>$userInfo['name'],
                "real_name"=>isset($userInfo['realname']) ? $userInfo['realname'] : "",
                "points"=> $newPoints,
                "token"=>$userInfo["token"],
                "sex"=> isset($userInfo["gender"]) ? intval($userInfo["gender"]) : 0,
                "head_id"=> isset($userInfo["head_url"]) ? intval($userInfo["head_url"]) : 1,
            ];
        }
        return FALSE;
    }
    
    /**
     * TODO 通过FD查询用户的TOKEN或用户ID值；
     * @param int $loginFd
     * @return array|array|string[][]|number[][]
     */
    public static function getLoginUser($loginFd,&$error='') {
        //正式登录；要更新REDIS数据；
        $logintokenKey = SysEnum::getLoginFdMapKey();
        $getChar = RedisTools::Pool_hGet($logintokenKey, "login_".$loginFd);
        $getChar = !empty($getChar) ? explode('-', $getChar): false ;
        $loginUid = isset($getChar[0]) ? intval($getChar[0]) : 0 ;
        if(!$getChar || empty($getChar) || $loginUid <= 0){
            $error = "用户身份失效";
            return false ;
        }
        $userRsKey = SysEnum::USER_LOGIN_REDIS_KEY.$loginUid;                                      //存储信息内容； 
        $userInfo = RedisTools::Pool_get($userRsKey);
        $userInfo = !empty($userInfo) ? json_decode($userInfo,true) : false ; 
        //玩家的实际分数；是DB查询到的
        $userInfo["points"] = self::getLoginUserPoints($loginUid);
        return $userInfo;
    }
    
    
    //随机生成 HEAD 的ID值
    public static function randerUserHeadId(){
        $tempval = mt_rand(0,7);
        return $tempval;
    }
    
    /**
     * TODO 登录玩家的实时分数
     * @param int $loginUid
     */
    public static function getLoginUserPoints($loginUid) {
        if(!$loginUid) return 0.0;
        $umodel = new User();
        $money = $umodel->getUserOneFields($loginUid,"points"); 
        if(isset($money) && floatval($money) >= 0){
            $money = bcadd(floatval($money), 0 , 2);
        }
        return floatval($money);
    }
    
    /**
     * TODO 获取多个玩家ID的实际分数
     * @param boolean $uids UIDS 
     * @return number
     */
    public static function getUserListPoints($uids = FALSE) {
        $lists = FALSE;
        if(!$uids) return $lists;
        try {
            $DBObj = DBTools::getPoolDB();              //DB连接对象；
            $lists  = $DBObj -> where('uid',$uids,'in') -> where('status',1) -> get('qc_user' ,1000 , ['uid','points','status']);
            DBTools::destPoolDB($DBObj);                //释放Pool
        } catch (\Exception $e) {
            BaseEnum::Logger("获取数据库连接失败=>".$e->getMessage());
            return FALSE;
        }
        return !empty($lists) ? array_column($lists, "points","uid") : FALSE;
    }
    

}